#include "linkedListAPI.h"



void i_linkedListInit(void)
{
  /* nothing needed at this time */
}

void i_linkedListInsert(ListPtr * pList, void * data, int dataSize)
{

  int i; 
  ListPtr currentListPtr = (*pList);
  ListPtr newListPtr;

  
  /* check if memory can be allocated */
  if((newListPtr = malloc(sizeof(List))) != NULL)
  {

    /* safety check - set pointer to NULL for known operation */
    newListPtr->next = NULL;


    /* create data storage area */
    newListPtr->data = malloc(dataSize);

    /* build data structure in new location */
    for (i = 0; i < dataSize; i++) 
    {

      /* individually assign value byte by byte */
      *(char *)(newListPtr->data + i) = *(char *)(data + i); 

    }

    /* list not populated */
    if(currentListPtr != NULL)
    {
      /* find NULL pointer (end of list) */
      while(currentListPtr->next != NULL) currentListPtr = currentListPtr->next;
    }
    else
    {
      *pList = newListPtr;
      return;
    }
    /* tack new list input onto end */
    currentListPtr->next = newListPtr;
  }
  else
  {
    /* let user know error */
    printf("MEMORY ALLOCATION ERROR!!!\n");
  }

}

unsigned int i_linkedListRemoveFirst(ListPtr * pList, void (*releaseFromMemoryCallBack)(void * data))
{
  
  ListPtr deletePtr;

  /* check to see if element exist */
  if((*pList) != NULL)
  {
    /* do specific memory free through call back */
    releaseFromMemoryCallBack((*pList)->data);
    /* map list element to be released */
    deletePtr = *pList;
    /* set beginning list element to next, de-thread first element */
    *pList = (*pList)->next;
    /* release first element in memory, release the de-threaded element */
    free(deletePtr);
    /* signal element removal successful */
    return 1;
  }
  /* signal no element to be removed from list */
  return 0;
}

int i_linkedListDoesExistInList(ListPtr * pList, void * compData, unsigned int (*compDataStructCallBack)(void * dataStruc, void * compData))
{
  ListPtr compPtr = *pList;
  unsigned int listPosition = 0;

  /* check if this list exists */
  if(compPtr != NULL)
  {
    /* looking for the end of the list? */
    while(compPtr != NULL)
    {
      /* Send Data Structure To Call Back Function for specific type comparison */
      if(compDataStructCallBack(compPtr->data, compData))
      {
        /* return found */
        return listPosition;
      }
      compPtr = compPtr->next;
      listPosition++;
    }
  }
  /* return failure */
  return -99;
}

void * i_linkedListGetDataFromPosition(ListPtr * pList, unsigned int position)
{
  ListPtr compPtr = *pList;
  unsigned int counter;

  /* filter NULL List */
  if(compPtr == NULL) return NULL;

  for(counter = 0; counter < position; counter++)
  {
    if(compPtr->next != NULL)
    {
      compPtr = compPtr->next;
    }
    else
    {
      return NULL;
    }
  }

  /* give pointer to data */
  return compPtr->data;

}

unsigned int i_linkedListEmpty(List **pList)
{
  return (NULL == pList);
}
